package com.loukou.lkt.lkt.service.impl;

import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.loukou.lkt.lkt.constant.Urls;
import com.loukou.lkt.lkt.dao.AllocationOrderDao;
import com.loukou.lkt.lkt.dao.AllocationOrderDetailDao;
import com.loukou.lkt.lkt.dao.GoodsStockDao;
import com.loukou.lkt.lkt.dao.GoodsStockLogDao;
import com.loukou.lkt.lkt.dao.PoPurchaseOrderDao;
import com.loukou.lkt.lkt.dao.PoPurchaseOrderDetailDao;
import com.loukou.lkt.lkt.dao.PoPurchaseReturnOrderDao;
import com.loukou.lkt.lkt.dao.PoPurchaseReturnOrderDetailDao;
import com.loukou.lkt.lkt.entity.AllocationOrder;
import com.loukou.lkt.lkt.entity.AllocationOrderDetail;
import com.loukou.lkt.lkt.entity.GoodsStock;
import com.loukou.lkt.lkt.entity.GoodsStockLog;
import com.loukou.lkt.lkt.entity.PoPurchaseOrder;
import com.loukou.lkt.lkt.entity.PoPurchaseOrderDetail;
import com.loukou.lkt.lkt.entity.PoPurchaseReturnOrder;
import com.loukou.lkt.lkt.enums.GoodsStockLogBusinessTypeEnum;
import com.loukou.lkt.lkt.enums.GoodsStockLogPositionStockStateEnum;
import com.loukou.lkt.lkt.enums.GoodsStockPositionTypeEnum;
import com.loukou.lkt.lkt.enums.GoodsStockStateEnum;
import com.loukou.lkt.lkt.enums.WmsInOrderTypeEnum;
import com.loukou.lkt.lkt.enums.WmsOutOrderTypeEnum;
import com.loukou.lkt.lkt.req.ChangeStockReq;
import com.loukou.lkt.lkt.req.WmsInOrderCallbackDetailReq;
import com.loukou.lkt.lkt.req.WmsInOrderCallbackReq;
import com.loukou.lkt.lkt.req.WmsOutOrderCallbackDetailReq;
import com.loukou.lkt.lkt.req.WmsOutOrderCallbackReq;
import com.loukou.lkt.lkt.resp.RespDto;
import com.loukou.lkt.lkt.resp.RespPhpDto;
import com.loukou.lkt.lkt.service.GoodsStockService;
import com.loukou.lkt.lkt.utils.GetUtils;
import com.loukou.lkt.lkt.utils.MD5;

@Service
public class GoodsStockServiceImpl implements GoodsStockService{
	@Autowired
	private GoodsStockDao goodsStockDao;
	@Autowired
	private GoodsStockLogDao goodsStockLogDao;
	@Autowired
	private PoPurchaseOrderDao poPurchaseOrderDao;
	@Autowired
	private PoPurchaseOrderDetailDao poPurchaseOrderDetailDao;
	@Autowired
	private AllocationOrderDao allocationOrderDao;
	@Autowired
	private AllocationOrderDetailDao allocationOrderDetailDao;
	@Autowired
	private PoPurchaseReturnOrderDao poReturnDao;
	@Autowired
	private PoPurchaseReturnOrderDetailDao poReturnDetailDao;
	
	/**
	 * 入库回调更新库存
	 */
	@Override
	@Transactional
	public RespDto<Integer> updateStockInOrder(WmsInOrderCallbackReq req) {
		RespDto<Integer> resp = new RespDto<Integer>();
		if (req==null || (req.getOrderType()!=WmsInOrderTypeEnum.TYPE_PURCHASE.getType() && req.getOrderType()!=WmsInOrderTypeEnum.TYPE_ALLOCATION.getType())) {
			resp.setCode(400);
			resp.setMsg("参数有误");
			return resp;
		}
		
		if(req.getOrderType()==WmsInOrderTypeEnum.TYPE_PURCHASE.getType()){//采购进货
			//获取采购单
			PoPurchaseOrder poPurchaseorder=poPurchaseOrderDao.findByOrderCode(req.getOutbizCode());
			if(poPurchaseorder == null){
				resp.setCode(402);
				resp.setMsg("采购单不存在");
				return resp;
			}
			
			for(WmsInOrderCallbackDetailReq inOrderDetail:req.getDetails()){
				PoPurchaseOrderDetail ppOrderDetail=poPurchaseOrderDetailDao.findOne(Integer.parseInt(inOrderDetail.getOutbizId()));
				if(ppOrderDetail == null){
					throw new RuntimeException("采购单明细不存在");
				}
				
				//查询库存参数
				int warehouseId=poPurchaseorder.getWarehouseId();
				int positionType=GoodsStockPositionTypeEnum.TYPE_Normal.getId();
				int goodsId=ppOrderDetail.getGoodsId();
				int normalStockState=GoodsStockStateEnum.STATE_Normal.getId();
				int inOrderStock=inOrderDetail.getReceiveNumber();
				
				//检查是否有库存记录
				GoodsStock goodsStockMsg=goodsStockDao.findByWarehouseIdAndPositionTypeAndGoodsIdAndStockState(warehouseId, positionType, goodsId, normalStockState);
				if(goodsStockMsg==null){
					GoodsStock stockDto=new GoodsStock();
					stockDto.setWarehouseId(warehouseId);
					stockDto.setPositionType(positionType);
					stockDto.setGoodsId(goodsId);
					stockDto.setStockState(normalStockState);
					stockDto.setStock(inOrderStock);
					goodsStockDao.save(stockDto);
				}else{
					//更新本地库存
					goodsStockDao.plusStock(warehouseId,positionType,goodsId,normalStockState,inOrderStock);
				}
				
				//更新本地库存log
				GoodsStockLog goodsStockLogReq=new GoodsStockLog();
				goodsStockLogReq.setGoodsId(goodsId);
				goodsStockLogReq.setPositionStockState(GoodsStockLogPositionStockStateEnum.STATE_Normal.getId());
				goodsStockLogReq.setQuantity(inOrderStock);
				goodsStockLogReq.setWarehouseId(warehouseId);
				goodsStockLogReq.setBusinessId(poPurchaseorder.getId());
				goodsStockLogReq.setBusinessCode(poPurchaseorder.getOrderCode());
				goodsStockLogReq.setBusinessType(GoodsStockLogBusinessTypeEnum.TYPE_PURCHASE.getId());
				goodsStockLogDao.save(goodsStockLogReq);
			}
		}else if(req.getOrderType()==WmsInOrderTypeEnum.TYPE_ALLOCATION.getType()){//调拨入库
			//获取调拨单
			AllocationOrder allocationOrder=allocationOrderDao.findByOrderCode(req.getOutbizCode());
			if(allocationOrder == null){
				resp.setCode(402);
				resp.setMsg("调拨单不存在");
				return resp;
			}
			
			for(WmsInOrderCallbackDetailReq inOrderDetail:req.getDetails()){
				AllocationOrderDetail aOrderDetail=allocationOrderDetailDao.findOne(Integer.parseInt(inOrderDetail.getOutbizId()));
				if(aOrderDetail == null){
					throw new RuntimeException("调拨单明细不存在");
				}
				
				//查询库存参数
				int warehouseId=allocationOrder.getInWarehouseId();
				int positionType=GoodsStockPositionTypeEnum.TYPE_Normal.getId();
				int goodsId=aOrderDetail.getInGoodsId();
				int normalStockState=GoodsStockStateEnum.STATE_Normal.getId();
				int inOrderStock=inOrderDetail.getReceiveNumber();
				
				//检查是否有库存记录
				GoodsStock goodsStockMsg=goodsStockDao.findByWarehouseIdAndPositionTypeAndGoodsIdAndStockState(warehouseId, positionType, goodsId, normalStockState);
				if(goodsStockMsg==null){
					GoodsStock stockDto=new GoodsStock();
					stockDto.setWarehouseId(warehouseId);
					stockDto.setPositionType(positionType);
					stockDto.setGoodsId(goodsId);
					stockDto.setStockState(normalStockState);
					stockDto.setStock(inOrderStock);
					goodsStockDao.save(stockDto);
				}else{
					//更新本地库存
					goodsStockDao.plusStock(warehouseId,positionType,goodsId,normalStockState,inOrderStock);
				}
				
				//更新本地库存log
				GoodsStockLog goodsStockLogReq=new GoodsStockLog();
				goodsStockLogReq.setGoodsId(goodsId);
				goodsStockLogReq.setPositionStockState(GoodsStockLogPositionStockStateEnum.STATE_Normal.getId());
				goodsStockLogReq.setQuantity(inOrderStock);
				goodsStockLogReq.setWarehouseId(warehouseId);
				goodsStockLogReq.setBusinessId(allocationOrder.getId());
				goodsStockLogReq.setBusinessCode(allocationOrder.getOrderCode());
				goodsStockLogReq.setBusinessType(GoodsStockLogBusinessTypeEnum.TYPE_ALLOCATION_IN.getId());
				goodsStockLogDao.save(goodsStockLogReq);
			}
		}
		
		return resp;
	}
	
	/**
	 * 出库回调更新库存
	 */
	@Override
	@Transactional
	public RespDto<Integer> updateStockOutOrder(WmsOutOrderCallbackReq req) {
		RespDto<Integer> resp = new RespDto<Integer>();
		if (req==null || (req.getOrderType()!=WmsOutOrderTypeEnum.TYPE_RETURN.getType() && req.getOrderType()!=WmsOutOrderTypeEnum.TYPE_ALLOCATION.getType())) {
			resp.setCode(400);
			resp.setMsg("参数有误");
			return resp;
		}
		
		if(req.getOrderType()==WmsOutOrderTypeEnum.TYPE_RETURN.getType()){//采购退货
			//获取退货单
			PoPurchaseReturnOrder poPurchaseReturnOrder=poReturnDao.findByOrderReturnCode(req.getOutbizCode());
			if(poPurchaseReturnOrder == null){
				resp.setCode(402);
				resp.setMsg("退货单不存在");
				return resp;
			}
			
			for(WmsOutOrderCallbackDetailReq outOrderDetail:req.getDetails()){
				PoPurchaseOrderDetail ppOrderDetail=poPurchaseOrderDetailDao.findOne(Integer.parseInt(outOrderDetail.getOutbizId()));
				if(ppOrderDetail == null){
					throw new RuntimeException("采购单明细不存在");
				}
				
				//查询库存参数
				int warehouseId=poPurchaseReturnOrder.getWarehouseId();
				int positionType=GoodsStockPositionTypeEnum.TYPE_Normal.getId();
				int goodsId=ppOrderDetail.getGoodsId();
				int normalStockState=GoodsStockStateEnum.STATE_Normal.getId();
				int outOrderStock=outOrderDetail.getDeliveryNumber();
				
				//检查是否有库存记录
				GoodsStock goodsStockMsg=goodsStockDao.findByWarehouseIdAndPositionTypeAndGoodsIdAndStockState(warehouseId, positionType, goodsId, normalStockState);
				if(goodsStockMsg==null){
					throw new RuntimeException("库存信息不存在，无法退货");
				}else{
					if(goodsStockMsg.getStock()-outOrderStock<0){
						throw new RuntimeException("库存不足，无法退货");
					}
					//更新本地库存
					goodsStockDao.minusStock(warehouseId,positionType,goodsId,normalStockState,outOrderStock);
				}
				
				//更新本地库存log
				GoodsStockLog goodsStockLogReq=new GoodsStockLog();
				goodsStockLogReq.setGoodsId(goodsId);
				goodsStockLogReq.setPositionStockState(GoodsStockLogPositionStockStateEnum.STATE_Normal.getId());
				goodsStockLogReq.setQuantity(outOrderStock);
				goodsStockLogReq.setWarehouseId(warehouseId);
				goodsStockLogReq.setBusinessId(poPurchaseReturnOrder.getId());
				goodsStockLogReq.setBusinessCode(poPurchaseReturnOrder.getOrderReturnCode());
				goodsStockLogReq.setBusinessType(GoodsStockLogBusinessTypeEnum.TYPE_RETURN.getId());
				goodsStockLogDao.save(goodsStockLogReq);
			}
		}else if(req.getOrderType()==WmsOutOrderTypeEnum.TYPE_ALLOCATION.getType()){//调拨入库
			//获取调拨单
			AllocationOrder allocationOrder=allocationOrderDao.findByOrderCode(req.getOutbizCode());
			if(allocationOrder == null){
				resp.setCode(402);
				resp.setMsg("调拨单不存在");
				return resp;
			}
			
			for(WmsOutOrderCallbackDetailReq outOrderDetail:req.getDetails()){
				AllocationOrderDetail aOrderDetail=allocationOrderDetailDao.findOne(Integer.parseInt(outOrderDetail.getOutbizId()));
				if(aOrderDetail == null){
					throw new RuntimeException("调拨单明细不存在");
				}
				
				//查询库存参数
				int warehouseId=allocationOrder.getOutWarehouseId();
				int positionType=GoodsStockPositionTypeEnum.TYPE_Normal.getId();
				int goodsId=aOrderDetail.getOutGoodsId();
				int normalStockState=GoodsStockStateEnum.STATE_Normal.getId();
				int outOrderStock=outOrderDetail.getDeliveryNumber();
				
				//检查是否有库存记录
				GoodsStock goodsStockMsg=goodsStockDao.findByWarehouseIdAndPositionTypeAndGoodsIdAndStockState(warehouseId, positionType, goodsId, normalStockState);
				if(goodsStockMsg==null){
					throw new RuntimeException("库存信息不存在，无法出库");
				}else{
					if(goodsStockMsg.getStock()-outOrderStock<0){
						throw new RuntimeException("库存不足，无法出库");
					}
					//更新本地库存
					goodsStockDao.minusStock(warehouseId,positionType,goodsId,normalStockState,outOrderStock);
				}
				
				//更新本地库存log
				GoodsStockLog goodsStockLogReq=new GoodsStockLog();
				goodsStockLogReq.setGoodsId(goodsId);
				goodsStockLogReq.setPositionStockState(GoodsStockLogPositionStockStateEnum.STATE_Normal.getId());
				goodsStockLogReq.setQuantity(outOrderStock);
				goodsStockLogReq.setWarehouseId(warehouseId);
				goodsStockLogReq.setBusinessId(allocationOrder.getId());
				goodsStockLogReq.setBusinessCode(allocationOrder.getOrderCode());
				goodsStockLogReq.setBusinessType(GoodsStockLogBusinessTypeEnum.TYPE_ALLOCATION_OUT.getId());
				goodsStockLogDao.save(goodsStockLogReq);
			}
		}
		
		return resp;
	}

	@Override
	/**
	 * type：
	(1)采购进货，直接加库存		上面的num就是新增的数量
	(2)采购退货，直接减库存		上面的num就是减去的数量
	(3)销售订单，减去库存、减去冻结		上面的num就是变化的数量
	(4)库存盘点，更新库存			上面的num就是需要更新成的数量
	(5)调拨入库					增加库存
	(6)调拨出库					减去库存
	 * @param req
	 * @param type
	 * @return
	 */
	public RespDto<Integer> changeWebStock(List<ChangeStockReq> req,int type) {
		RespDto<Integer> resp = new RespDto<Integer>();
		if(req == null || req.size()==0 || type>4 || type<1){
			resp.setCode(401);
			resp.setMsg("参数为空");
			return resp;
		}
		
		String chagedata="";
		for(ChangeStockReq cs : req){
			chagedata+=cs.getSpecId()+":"+cs.getQuantity();
		}
		
		String url=Urls.LktTellWebChangeStockNotice;
		
		Date time=new Date();
		String code=MD5.GetMD5Code("app_key=lkt_stock&time="+time+"lkt_stock@!#");
		url=url+"&act=changestock&"+chagedata+"&type"+type+"&app_key=lkt_stock&time"+time+"&code"+code;
		
		Object result=GetUtils.getPhpData(url);
		
		RespPhpDto r = (RespPhpDto) result;
		resp.setCode(r.getCode());
		resp.setMsg(r.getMsg());
		return resp;
	}
}
